﻿#ifndef OPENGL_GP_LIB_H
#define OPENGL_GP_LIB_H

#if defined(_WIN32) || defined(__CYGWIN__)
    #define OS_WIN
#endif
#if defined(__GNUC__) || defined(__GNUG__)
    #define OS_LINUX
#endif

#ifdef OPENGL_GPDLLEXPORT
    #if defined(OS_WIN)
        #define OPENGL_GP_LIBDLL __declspec(dllexport)
    #elif defined(OS_LINUX)
        #define OPENGL_GP_LIBDLL __attribute__((visibility("default")))
    #else
        #define OPENGL_GP_LIBDLL
//__declspec(dllexport)
    #endif
#else
    #if defined(OS_WIN)
        #define OPENGL_GP_LIBDLL __declspec(dllimport)
    #elif defined(OS_LINUX)
        #define OPENGL_GP_LIBDLL __attribute__((visibility("default")))
    #else
        #define OPENGL_GP_LIBDLL
//__declspec(dllimport)
    #endif
#endif

#if defined(OS_WIN)
#ifndef OPENGL_GPDLLEXPORT
// 导出两个符号值 可以使用程序在win 平台默认使用这两个厂商的显卡执行opengl环境
// N卡使用独显运行
extern "C" __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
// A显卡使用独显运行
extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif
#endif

#define OPENGL_GP_LIBCALLMODE

/*
 * opengl es 3.1 glBindImageTexture 支持的格式如下
| Image Unit Format | Format Qualifier |
| ----------------- | ---------------- |
| GL_RGBA32F        | rgba32f          |
| GL_RGBA16F        | rgba16f          |
| GL_R32F           | r32f             |
| GL_RGBA32UI       | rgba32ui         |
| GL_RGBA16UI       | rgba16ui         |
| GL_RGBA8UI        | rgba8ui          |
| GL_R32UI          | r32ui            |
| GL_RGBA32I        | rgba32i          |
| GL_RGBA16I        | rgba16i          |
| GL_RGBA8I         | rgba8i           |
| GL_R32I           | r32i             |
| GL_RGBA8          | rgba8            |    //这个测试过 glsl报错
| GL_RGBA8_SNORM    | rgba8_snorm      |
*/

typedef enum{
    GLF_R8UI=0,   //单通道无符号8位数据
    GLF_R16UI,   //单通道无符号16位数据
    GLF_R32UI,   //单通道无符号16位数据

    GLF_RGB8UI,    //三通道无符号8位数据
    GLF_RGB16UI,    //三通道无符号16位数据
    GLF_RGB32UI,    //三通道无符号32位数据

    GLF_RGBA8UI,    //四通道无符号8位数据
    GLF_RGBA16UI,    //四通道无符号16位数据
    GLF_RGBA32UI,    //四通道无符号32位数据

    GLF_R8I,   //单通道8位整数数据
    GLF_R16I,   //单通道16位整数数据
    GLF_R32I,   //单通道16位整数数据

    GLF_RGB8I,    //三通道8位整数数据
    GLF_RGB16I,    //三通道16位整数数据
    GLF_RGB32I,    //三通道32位整数数据

    GLF_RGBA8I,    //四通道8位整数数据
    GLF_RGBA16I,    //四通道16位整数数据
    GLF_RGBA32I,    //四通道16位整数数据

    GLF_R32F,       //单通道32位浮点数据
    GLF_RG32F,      //双通道32位浮点数据
    GLF_RGB32F,      //三通道32位浮点数据
    GLF_RGBA32F,     //四通道32位浮点数据
}GLGPFromatEnum;

#if defined(__cplusplus)||defined(c_plusplus)
extern "C"{
#endif


OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpTest(unsigned int program,int width,int height,void *misc);  //开发测试用的函数

/*! @brief 返回库中初始化opengl context 最大数量.
 *  参考 @ref glgpSetMaxGLContext
 *  @param[in]
 *  @return 返回库中初始化opengl context 最大数量
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程可调用.
 *  @sa @ref glgpSetMaxGLContext glgpInitContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpGetMaxGLContext(void);

/*! @brief 初始化本库之前，用来设置在主线程中初始化多少个opengl context.
 *  应在 @ref glgpInitContext 前调用，设置初始化时建立的opengl context 数量
 *  这些context都使用相同的opengl版本(opengl es 3.2)
 *  @param[in] maxCtx 设置在库内建立多少个opengl context.
 *  @return void
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 必须在程序主线程中执行.
 *  @sa @ref glgpInitContext glgpGetMaxGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpSetMaxGLContext(int maxCtx);

/*! @brief 在主线程中初始化这个库(必须在程序的主线程中调用).
 *  这个函数在程序的整个生命周期应该只被调用一次。程序结束时调用 @ref releaseLibContext
 *  用于释放库的资源和对系所做的修改。
 *  @param[in] void.
 *  @return 成功则返回零
 *  @note
 *  @remark 注意在重新初始化时，函数里面会等其它线程释放opengl context (@ref glgpLockGLContext)，
 *  这可能会导致死锁
 *  @errors 执行出错的代码包括 @ref Not Zero
 *  @thread_safety 这个函数必须在程序主线程中执行.
 *  @sa @ref glgpSetMaxGLContext glgpGetMaxGLContext releaseLibContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpInitContext(void);

/*! @brief 在程序退出时用于释放库的资源和对系所做的修改(必须在程序的主线程中调用).
 *  释放库资源  参考 @ref initLibContext
 *  @param[in] void.
 *  @return 成功则返回零
 *  @note
 *  @remark 注意在所有用到opengl context的线程不再锁定context才能调用 (@ref glgpLockGLContext)
 *  @errors 执行出错的代码包括 @ref Not Zero
 *  @thread_safety 这个函数必须在程序主线程中执行.
 *  @sa @ref glgpInitContext glgpSetMaxGLContext glgpGetMaxGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpReleaseContext(void);

/*! @brief 接收库内部创建的窗口的消息，转换为事件分发给回调函数，在没有消息机制的应用程序中循环调用本函数以保证系统不会认为内部窗口没有响应.
 *  @param[in] void.
 *  @return void
 *  @note
 *  @remark 这个函数必须在 @ref glgpInitContext 初始化opengl context之后调用，
 *  如果应用程序有自己的窗口消息处理循环，可以不使用这个函数。
 *  @errors
 *  @thread_safety 这个函数必须在程序主线程中执行.
 *  @sa @ref glgpInitContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpPollGlfwEvents(void);


/*! @brief 在任何线程中，使用GLGP进行内存或计算操作前必须先锁定opengl context
 *  与 @ref glgpUnlockGLContext 成对使用，包裹着其它opengl通用计算操作函数
 *  @param[in] ctx_index 锁定的opengl context索引，范围 0 ~ @ref glgpGetMaxGLContext.
 *  应该与 @ref glgpUnlockGLContext 输入的索引一致
 *  @return
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程都可执行.
 *  @sa @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpLockGLContext(int ctx_index);

/*! @brief 在任何线程中，使用GLGP进行内存或计算操作前必须先锁定opengl context
 *  与 @ref glgpUnlockGLContext 成对使用，包裹着其它opengl通用计算操作函数
 *  @param[in] ctx_index 锁定的opengl context索引，范围 0 ~ @ref glgpGetMaxGLContext.
 *  应该与 @ref glgpUnlockGLContext 输入的索引一致
 *  @return 锁定成功返回非0，失败返回0
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程都可执行.
 *  @sa @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTrylockGLContext(int ctx_index);

/*! @brief 使用GLGP进行内存或计算操作后必须解锁opengl context
 * 与 @ref glgpTrylockGLContext 或 @ref glgpLockGLContext 成对使用，
 * 包裹着其它opengl通用计算操作函数
 *  @param[in] ctx_index 解锁的opengl context索引，范围 0 ~ @ref glgpGetMaxGLContext.
 *  应该与 @ref glgpLockGLContext 输入的索引一致
 *  @return 成功则返回零
 *  @note
 *  @remark 注意在所有用到opengl context的线程不再锁定context才能调用
 *  @errors 执行出错的代码包括 @ref Not Zero
 *  @thread_safety 这个函数必须在程序主线程中执行.
 *  @sa @ref releaseLibContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpUnlockGLContext(int ctx_index);

/*! @brief 编译给定的顶点着色器、片段着色器、计算着色，返回链接后的程序
 *  @param[in] ctx_index 解锁的opengl context索引，范围 0 ~ @ref glgpGetMaxGLContext.
 *  应该与 @ref glgpLockGLContext 输入的索引一致
 *  @return 成功则返回着色器程序代号，失败返回小于1的值。
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL unsigned int OPENGL_GP_LIBCALLMODE glgpComplieShaderProgram3(const char* const vertcode,const char* const fragcode,const char* const computecode);

/*! @brief 设置着色器程序中的Uniform常量值
 *  @param[in] program 要设置的目标着色器程序
 *  @param[in] type 要设置的Uniform 的数据类型 'i':整数 'u':无符号整数 ‘f’:浮点数 'd':双精度浮点 'm':单精度4x4矩阵
 *  @param[in] location 要设置的Uniform 的布局位置 layout(location=?)
 *  @param[in] arraysize 如果Uniform是数组 这参数输入数组长度，否则为1
 *  @param[in] len Uniform类型所含有的基本类型个数 例如 vec4 为 4 个float
 *  @param[in] data 源数据指针
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpComplieShaderProgram3 @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpSetUniformByLoc(unsigned int program,int location,
                                                           char type,int arraysize,int len,const void *data);


/*! @brief 设置着色器程序中的Uniform常量值
 *  @param[in] program 要设置的目标着色器程序
 *  @param[in] type 要设置的Uniform 的数据类型 'i':整数 'u':无符号整数 ‘f’:浮点数 'd':双精度浮点 'm':单精度4x4矩阵
 *  @param[in] uniformname 要设置的Uniform 的名称
 *  @param[in] arraysize 如果Uniform是数组 这参数输入数组长度，否则为1
 *  @param[in] len Uniform类型所含有的基本类型个数 例如 vec4 为 4 个float
 *  @param[in] data 源数据指针
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpComplieShaderProgram3 @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpSetUniform(unsigned int program,const char * const uniformname,
                                                           char type,int arraysize,int len,const void *data);

/*! @brief 删除编译链接好的着色器程序 @ref glgpComplieShaderProgram3
 *  @param[in] program 编译链接好的着色器程序
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpComplieShaderProgram3 @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpDeleteShaderProgram(unsigned int program);

/*! @brief 通过 glDispatchCompute()函数调用编译链接好的着色器程序
 *  @param[in] program 编译链接好的着色器程序
 *  @param[in] workgroup_x 线程工作全局工作组x维度的大小，参考glDispatchCompute()
 *  @param[in] workgroup_y 线程工作全局工作组x维度的大小，参考glDispatchCompute()
 *  @param[in] workgroup_z 线程工作全局工作组x维度的大小，参考glDispatchCompute()
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpComplieShaderProgram3 @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpInvokeComputeProgram(unsigned int program,
                                                                     unsigned int workgroup_x,
                                                                     unsigned int workgroup_y,
                                                                     unsigned int workgroup_z
                                                                     );

/*! @brief 申请分配一个opengl 2d纹理对象(内存)
 *  @param[in] format 纹理的格式
 *  @param[in] width 纹理的宽度
 *  @param[in] height 纹理的高度
 *  @param[in] intdata 初始化的源数据指针,为NULL时不进行初始化
 *  @return 成功则返回纹理对象代号，失败返回小于1的值。
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL unsigned int OPENGL_GP_LIBCALLMODE glgpAllocateGLTexture2D(GLGPFromatEnum format,int width,int height,void *intdata);


/*! @brief 获取申请分配到的一个opengl 2d纹理对象信息(宽高、通道数、数据类型)
 *  @param[in] tex 获取信息的纹理对象
 *  @param[out] width 返回纹理对象宽度, NULL指针不进行赋值
 *  @param[out] height 返回纹理对象高度, NULL指针不进行赋值
 *  @param[out] numComponents 返回纹理对象通道数量, NULL指针不进行赋值
 *  @param[out] dbytesize 返回纹理对象通道的每个数据所点的字节数，通常为 1, 2, 4
 *  @param[out] dtype 返回纹理对象数据类型, NULL指针不进行赋值, "f":浮点 "u":无符号整数 "i":整数,
 *              调用方要保证指针指向的缓冲区不小于1个字节
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpGetTexture2DInfo(unsigned int tex,
                                                                 int *width,int *height,int *numComponents,
                                                                 int *dbytesize,
                                                                 char *dtype);

/*! @brief 绑定申请分配到的一个opengl 2d纹理对象(内存)到图像操作单元，内部调用glBindImageTexture()来实现
 * glBindImageTexture(unit,tex,0,GL_FALSE,0,GL_READ_WRITE,texformat);
 *  @param[in] locate 绑定到的目标单元
 *  @param[in] tex 纹理对象
 *  @param[in] texformat 纹理对象的格式
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpBindImageTexture(unsigned int unit,
                                                                 unsigned int tex
                                                                 );

/*! @brief 删除申请分配到的一个opengl 2d纹理对象(内存)
 *  @param[in] tex 申请到纹理
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpDeleteGLTexture(unsigned int tex);

/*! @brief 删除申请分配到的多个opengl 2d纹理对象(内存)
 *  @param[in] tex 申请到纹理
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpDeleteGLTextures(int len,unsigned int *texs);

/*! @brief 将固定颜色值填充到申请分配到的一个opengl 2d纹理对象内存
 *  @param[in] tex 申请到纹理,仅支持单通道或四通道的纹理
 *  @param[in] r 颜色值第一通道
 *  @param[in] g 颜色值第二通道
 *  @param[in] b 颜色值第三通道
 *  @param[in] a 颜色值第四通道
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpFillTexture(unsigned tex,
                                                           float r,float g,float b,float a,
                                                           int colormask
                                                           );

/*! @brief 设置申请分配到的一个opengl 2d纹理对象内存内部颜色通道排列顺序
 *  @param[in] tex 申请到纹理,支持1~4通道的纹理
 *  @param[in] swizzle 重排的顺序，默认顺序为"rgba"，例如可设置为常数其它顺序"bgr1"或"bgr0",常数只支持1 或 0
 *              常量不会对无符号8位自动扩展为255，所以要注意
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext,这个函数只是设置了纹理的内部通道顺序，并不会调整内存，
 *          如果要调整内存需要对 tex 进行采样再写回到 tex里才行，例如设置新顺序后调用 @glgpTextureCopy 自己复制自己
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpSetTexSwizzle(unsigned tex,const char *swizzle);

/*! @brief 把系统内存放置到申请分配到的一个opengl 2d纹理对象内存里
 *  @param[in] tex 申请到纹理
 *  @param[in] dataformat 目标内存格式
 *  @param[in] width  目标纹理的宽度
 *  @param[in] height 目标纹理的高度
 *  @param[in] data  源数据内存指针
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpSetTexImage2D(unsigned int tex,void* data);     //GLFromatEnum dataformat,int width,int height,



/*! @brief 把申请分配到的一个opengl 2d纹理对象内存内容复制到 主机内存的data指向的内存
 *  @param[in] tex 申请到纹理
 *  @param[in] dataformat 复制的目标内存格式
 *  @param[in] width 从源纹理复制的宽度
 *  @param[in] height 从源纹理复制的高度
 *  @param[in] data 复制的目标内存指针
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpAllocateGLTexture2D @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpGetTexImage2D(unsigned int tex,void* data); //GLFromatEnum dataformat,int width,int height,


//STREAM: 数据被修改一次，最多被使用少数几次; STATIC: 数据被修改一次，无限次使用; DYNAMIC: 数据经常被修改，无限次使用
//DRAW: 数据内容由cpu修改，然后用于gpu绘制或图像相关命令; READ: 数据内容由gpu修改，然后用于cpu查询获取数据内存; COPY: 数据内容由gpu修改，然后用于gpu绘制或图像相关命令;
typedef enum{
    GLGP_BUF_USAGE_STREAM_DRAW = 0,     //流式写入用法，缓冲区的内容将会被cpu修改一次并最多由gpu用于绘制或图像相关命令少数几次
    GLGP_BUF_USAGE_STREAM_READ,          //流式只读用法，缓冲区的内容将会被gpu(例如从opengl读取数据)修改一次并最多由cpu查询获取数据少数几次
    GLGP_BUF_USAGE_STREAM_COPY,         //流式复制用法，缓冲区的内容将会被gpu(例如从opengl读取数据)修改一次并最多由gpu作为源用于绘制或图像相关的命令少数几次
    GLGP_BUF_USAGE_STATIC_DRAW,          //静态写入用法，缓冲区的内容将会被cpu修改一次并由gpu用于绘制或图像相关命令无限多次
    GLGP_BUF_USAGE_STATIC_READ,         //静态只读用法，缓冲区的内容将会被gpu(例如从opengl读取数据)修改一次并由cpu查询获取数据无限多次
    GLGP_BUF_USAGE_STATIC_COPY,         //静态复制用法，缓冲区的内容将会被gpu(例如从opengl读取数据)修改一次并由gpu作为源用于绘制或图像相关的命令无限多次
    GLGP_BUF_USAGE_DYNAMIC_DRAW,        //动态写入用法，缓冲区的内容将会被cpu重复修改并由gpu用于绘制或图像相关命令无限多次
    GLGP_BUF_USAGE_DYNAMIC_READ,        //动态只读用法，缓冲区的内容将会被gpu(例如从opengl读取数据)重复修改并由cpu查询获取数据无限多次
    GLGP_BUF_USAGE_DYNAMIC_COPY,        //动态复制用法，缓冲区的内容将会被gpu(例如从opengl读取数据)重复修改并由gpu作为源用于绘制或图像相关的命令无限多次
} GLGPBufferUsageHint;  //

typedef enum{
    GLGP_PBO_ToOpenGL = 0,      //用于将cpu内存写到gpu的方向, 相当于GL_PIXEL_UNPACK_BUFFER
    GLGP_PBO_FromOpenGL         //用于将gpu显存写到cpu的方向, 相当于GL_PIXEL_PACK_BUFFER
} GLGPPBO_Type;

/*! @brief 申请分配到的一个opengl 像素缓冲区对象，通常用于GPU自动读取或写入主机内存以减小CPU内存操作时间
 *  @param[in] type 申请的像素缓冲区类型 @ref GLGPPBO_Type
 *  @param[in] usagehint 申请的像素缓冲区的用途提示,提示gpu进行一定的性能优化，参考 @ref GLGPBufferUsageHint
 *  @param[in] bytesize 申请的像素缓冲区的大小，单位为字节
 *  @return 成功返回像素缓冲区对象UID，失败返回零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpDeleteGLBufferObj  @ref glgpDeleteGLBufferObjects
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL unsigned int OPENGL_GP_LIBCALLMODE glgpAllocateGLPixelBufferObj(int type, int usagehint, size_t bytesize);


/*! @brief 将申请分配到的一个opengl 像素缓冲区对象映射到cpu可访问的内存地址
 *  @param[in] pboid 分配到的opengl像素缓冲区对象id
 *  @param[in] type 申请到的像素缓冲区类型 @ref GLGPPBO_Type
 *  @return 成功返回内存指针，失败返回NULL指针
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext,
 *          返回的指针要unmap才能删除PBO @ref glgpUnmapPBOMemory @ref glgpDeleteGLBufferObj
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpAllocateGLPixelBufferObj @ref glgpUnmapPBOMemory
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void * OPENGL_GP_LIBCALLMODE glgpMapPBOMemory(unsigned int pboid,int type);

/*! @brief 将申请分配到的一个opengl 像素缓冲区对象解除映射到cpu可访问的内存地址
 *  @param[in] pboid 分配到的opengl像素缓冲区对象id
 *  @param[in] type 申请到的像素缓冲区类型 @ref GLGPPBO_Type
 *  @return 成功返回零，失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext,
 *          PBO要unmap才能删除PBO @ref glgpUnmapPBOMemory @ref glgpDeleteGLBufferObj
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpAllocateGLPixelBufferObj @ref glgpMapPBOMemory
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpUnmapPBOMemory(unsigned int pboid,int type);


/*! @brief 将申请分配到的一个opengl 像素缓冲区对象的内容复制到2维纹理对像中,该操作是由gpu异步完成的
 *  @param[in] pboid 分配到的opengl像素缓冲区对象id,申请时其类型应该为GLGP_PBO_ToOpenGL @ref GLGPPBO_Type， 字节大小应该与目标纹理dsttex一致
 *  @param[in] dsttex 目标纹理,其等效字节大小应该与PBO一致
 *  @return 成功返回零，失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *          如果PBO进行了内存映射，必须解除才可以执行本函数 @ref glgpUnmapPBOMemory，否则会报错;
 *          本函数是异步的，如果要等完成，可以使用@ref glgpClientWaitSync 或 @ref glgpClientWait等待操作完成
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpAllocateGLPixelBufferObj @ref glgpAllocateGLTexture2D
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpAsyncCopyPBOtoTex2D(unsigned int pboid, unsigned int dsttex);


/*! @brief 将2维纹理对像中内容复制到像素缓冲区对象中,该操作是由gpu异步完成的
 *  @param[in] srctex 目标纹理,其等效字节大小应该与PBO一致
 *  @param[in] pboid 分配到的opengl像素缓冲区对象id,申请时其类型应该为GLGP_PBO_FromOpenGL @ref GLGPPBO_Type， 字节大小应该与源纹理srctex一致
 *  @return 成功返回零，失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *          如果PBO进行了内存映射，必须解除才可以执行本函数 @ref glgpUnmapPBOMemory，否则会报错;
 *          本函数是异步的，如果要等完成，可以使用@ref glgpClientWaitSync 或 @ref glgpClientWait等待操作完成
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpAllocateGLPixelBufferObj @ref glgpAllocateGLTexture2D
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpAsyncCopyTex2DtoPBO( unsigned int srctex, unsigned int pboid);

/*! @brief 删除申请分配到的一个opengl缓冲区对象
 *  @param[in] bufid 请分配到的一个opengl缓冲区对象id
 *  @return 成功返回0,失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext;
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpDeleteGLBufferObj(unsigned int bufid);

/*! @brief 删除申请分配到的多个opengl缓冲区对象
 *  @param[in] len 要删除的缓冲对象个数
 *  @param[in] bufids 请分配到的多个opengl缓冲区对象id指针，由调用方申请和释放内存
 *  @return 成功返回0,失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpDeleteGLBufferObjects(int len, unsigned int *bufids);

/*! @brief 通过glFenceSync()获取用于着色器计算完成条件的栅栏对象,使用完毕应该调用 @ref glDeleteSync 进行删除
 *  @param[in]
 *  @return 返回栅栏对象指针
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpClientWaitSync @ref glDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void *glgpGetFenceSync();

/*! @brief 删除通过glFenceSync()获取用于着色器计算完成条件的栅栏对象
 *  @param[in] sync 通过glFenceSync()获取用于着色器计算完成条件的栅栏对象指针
 *  @return void
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpClientWaitSync @ref glgpGetFenceSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpDeleteSync(void * sync);

/*! @brief 阴宽线程等待opengl执行到 glgpGetFenceSync() 获得的sync生成的地方的命令，内部通过glClientWaitSync()实现
 *  @param[in] sync 通过glFenceSync()获取用于着色器计算完成条件的栅栏对象指针
 *  @param[in] timeout_ns  超时时间 单位纳秒
 *  @return int, 等待同步完成没有超时则返回0，发生错误或超时返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpClientWaitSync(void * sync, unsigned long long timeout_ns);

/*! @brief glgpClientWaitSync的一步到位版本，获取fence 等待fence sync同步，返回前删除fence
 *  @param[in] timeout_ns  超时时间 单位纳秒
 *  @return int, 超时或错误返回非零，正常同步返回0
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync @ref glgpClientWaitSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpClientWait(unsigned long long timeout_ns);

/*! @brief 把无符号整数类型的纹理转换为 单精度浮点类型的纹理
 *  @param[in] srctex源纹理 必须为无符号整数类型纹理，1~4通道都支持
 *  @param[in] dsttex 目标纹理 必须为单精度浮点类型纹理，可以为单通道 双通道 三通道 四通道
 *  @param[in] width 纹理的宽度 源和目标必须相同
 *  @param[in] height 纹理的高度 源和目标必须相同
 *  @param[in] alpha 转换过程中 dst = alpha * src + beta
 *  @param[in] beta 转换过程中 dst = alpha * src + beta
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext,源纹理数据类型必须为无符号整数，
 *  目标纹理数据类型必须为单精度浮点数
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpCvtUItoFloat(unsigned int srctex,unsigned int dsttex,
                                                             float alpha,float beta,int colormask); //int width,int height,


/*! @brief 把 单精度浮点类型的纹理 转换为 无符号整数类型的纹理
 *  @param[in] srctex  源纹理 必须为单精度浮点类型纹理，1~4通道都支持
 *  @param[in] dsttex 目标纹理 必须为无符号整数类型纹理，可以为单通道 四通道 不支持三通道 或 双通道
 *  @param[in] width 纹理的宽度 源和目标必须相同
 *  @param[in] height 纹理的高度 源和目标必须相同
 *  @param[in] alpha 转换过程中 dst = alpha * src + beta
 *  @param[in] beta 转换过程中 dst = alpha * src + beta
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext,源纹理数据类型必须为单精度浮点数，
 *  目标纹理数据类型必须为无符号整数
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpCvtFloatToUI(unsigned int srctex,unsigned int dsttex,
                                                            float alpha,float beta,int colormask); //int width,int height,

/*! @brief 把源纹理的内容二进制复制到目标纹理,源和目标纹理宽高、内部格式必须相同
 *  @param[in] srctex  源纹理,可以为单通道 四通道 不支持三通道 或 双通道
 *  @param[in] dsttex 目标纹理 可以为单通道 四通道 不支持三通道 或 双通道
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpBlitTexture2D(unsigned int srctex,unsigned int dsttex);

/*! @brief 把源纹理的内容复制到目标纹理(以目标纹理的宽高为复制宽高)
 *  @param[in] srctex  源纹理,宽高必须大于等于目标纹理, 1~4通道都支持
 *  @param[in] dsttex 目标纹理 可以为单通道 四通道 不支持三通道 或 双通道
 *  @param[in] alpha 转换过程中 dst = alpha * src + beta
 *  @param[in] beta 转换过程中 dst = alpha * src + beta
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTextureCopy(unsigned int srctex,unsigned int dsttex,
                                                           float alpha,float beta,int colormask);


/*! @brief 把源纹理的内容复制到目标纹理(以源纹理的宽高为复制宽高),可用于纹理填充边界
 *  @param[in] srctex  源纹理 1~4通道都支持
 *  @param[in] dsttex 目标纹理,宽高必须大于等于源纹理 ,可以为单通道 四通道 不支持三通道 或 双通道
 *  @param[in] xoffset 位置偏移 dst(xoffset,yoffset) = src(0,0)
 *  @param[in] yoffset 位置偏移 dst(xoffset,yoffset) = src(0,0)
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTextureCopySrc(unsigned int srctex,unsigned int dsttex,
                                                              int xoffset,int yoffset,int colormask);


/*! @brief 把源纹理拆分复制到最多四个通道的目标纹理中
 *  @param[in] srctex  源纹理 1~4通道都支持， 小于四通道时 alpha通道默认全是 1
 *  @param[in] dsttexR 第一通道目标纹理 应该为单通道， 纹理宽高和数据格式必须与源纹理一致, 为0不输出
 *  @param[in] dsttexG 第二通道目标纹理 应该为单通道， 纹理宽高和数据格式必须与源纹理一致, 为0不输出
 *  @param[in] dsttexB 第三通道目标纹理 应该为单通道， 纹理宽高和数据格式必须与源纹理一致, 为0不输出
 *  @param[in] dsttexA 第四通道目标纹理 应该为单通道， 纹理宽高和数据格式必须与源纹理一致, 为0不输出
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpSplitTexture(unsigned int srctex,
                                                            unsigned int dsttexR,unsigned int dsttexG,unsigned int dsttexB,unsigned int dsttexA
                                                            );

/*! @brief 把最多四个源纹理合并为多通道纹理并复制内容目标纹理中
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道
 *  @param[in] srctexR 第一通道源纹理 应该为单通道， 纹理宽高和数据格式必须与目标纹理一致, 为0则该通道全是0
 *  @param[in] srctexG 第二通道源纹理 应该为单通道， 纹理宽高和数据格式必须与目标纹理一致, 为0则该通道全是0
 *  @param[in] srctexB 第三通道源纹理 应该为单通道， 纹理宽高和数据格式必须与目标纹理一致, 为0则该通道全是0
 *  @param[in] srctexA 第四通道源纹理 应该为单通道， 纹理宽高和数据格式必须与目标纹理一致, 为0则该通道全是0
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpMergeTextures(unsigned int dsttex,
                                                             unsigned int srctexR,unsigned int srctexG,unsigned int srctexB,unsigned int srctexA
                                                             );

/*! @brief 将源纹理按目标纹理宽高缩放后放置到目标纹理中
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[inout] dsttex  目标纹理 仅支持单通道或四通道
 *  @param[in] width 缩放新的宽度
 *  @param[in] height 缩放新的高度
 *  @param[in] interpolationMode 插值方式，0:周围四点线性插值(GL_LINEAR)，1:附近点插值(GL_NEAREST)
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpResizeTexture(unsigned int srctex,unsigned int dsttex,int interpolationMode);


typedef enum{
    GLGP_THRESH_BINARY=0,     // 二值化模式；大于thresh 的像素变更为 maxval，其它变更为0
    GLGP_THRESH_BINARY_INV, // 反向二值化模式；大于thresh 的像素变更为 0，其它变更为maxval
    GLGP_THRESH_TRUNC,      // 上截断模式；大于thresh 的像素变更为 thresh，其它保留为原始值
    GLGP_THRESH_TOZERO,     // 下截断模式；大于thresh 的像素保留为原始值，其它变更为0
    GLGP_THRESH_TOZERO_INV, // 反向下截断模式；大于thresh 的像素它变更为0，其它保留为原始值
    GLGP_THRESH_RANGE,      // 范围截断模式： 在thresh 和 maxval之的像素保留原始值，其它变更为0
} GLGPThreshType;
/*! @brief 把源纹理进行阈值运算后放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] thresh  阈值
 *  @param[in] maxval 当type = GLGP_THRESH_BINARY 或 GLGP_THRESH_BINARY_INV 时使用
 *  @param[in] type 进行阈值运算的模式
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTextureThreshold(unsigned int srctex,unsigned int dsttex,
                                                                float thresh,float maxval,int type,
                                                                int colormask
                                                                );


/*! @brief 把源纹理感兴趣区域提取出来放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理,不能与源纹理相等, 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] xoffset 感兴趣区域为 左上角点(xoffset,yoffset),区域宽x长 = (dsttex.width,dsttex.height)
 *  @param[in] yoffset 感兴趣区域为 左上角点(xoffset,yoffset),区域宽x长 = (dsttex.width,dsttex.height)
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTextureROI(unsigned int srctex,unsigned int dsttex,
                                                          int xoffset,int yoffset,int colormask
                                                          );


typedef enum{
    GLGP_TEXELMATH_LINEAR=0, // 每个纹理元素进行 dst = alpha * src + beta
    GLGP_TEXELMATH_POW,     // 每个纹理元素进行幂运算 dst = power(src,alpha)
    GLGP_TEXELMATH_EXP,     // 每个纹理元素进行以e为底数的幂运算 dst = exp(src) = power(e,src)
    GLGP_TEXELMATH_EXP2,     // 每个纹理元素进行以e为底数的幂运算 dst = power(2,src)
    GLGP_TEXELMATH_LOG,     // 每个纹理元素进行以e为底进行对数运算 dst = log_e(src)
    GLGP_TEXELMATH_LOG2,     // 每个纹理元素进行以2为底进行对数运算 dst = log_2(src)
    GLGP_TEXELMATH_AMPLITUDE,   //第一通道纹理元素平方加上第二通道纹理元素平方后开根号(复数幅值)，线性变换结果放到第一通道,dst.r = alpha * sqrt(power(src.r,2) + power(src.g,2)) + beta
} GLGPTexelMathMode;
/*! @brief 把源纹理里面的每个元素进行简单数学运算，然后放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] alpha  详见 @ref GLGPTexelMathMode
 *  @param[in] beta  详见 @ref GLGPTexelMathMode
 *  @param[in] mode  详见 @ref GLGPTexelMathMode
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTexelMath(unsigned int srctex,unsigned int dsttex,
                                                         float alpha,float beta,int mode,
                                                         int colormask
                                                         );


typedef enum{
    GLGP_TEXTURESMATH_ADD=0,    //  两个源纹理相加结果放置到目标纹理中 dst = src1 + src2
    GLGP_TEXTURESMATH_SUB,      //  两个源纹理相减结果放置到目标纹理中 dst = src1 - src2
    GLGP_TEXTURESMATH_MUL,      //  两个源纹理相乘结果放置到目标纹理中 dst = src1 * src2
    GLGP_TEXTURESMATH_DIV,      //  两个源纹理相除结果放置到目标纹理中 dst = src1 / src2
    GLGP_TEXTURESMATH_AMPLITUDE,  //  两个源纹理(复数)幅值结果放置到目标纹理中 dst = sqrt(pow(src1,2) + pow(src2,2))
}GLGPTexturesMathMode;
/*! @brief 将两个纹理进行简单数学运算，然后放置到目标纹理
 *  @param[in] srctex1  源纹理 支持1~4通道,数据类型必须与目标纹理相同
 *  @param[in] srctex2  源纹理 支持1~4通道,数据类型必须与目标源纹理相同
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTexturesMath(unsigned int srctex1,unsigned int srctex2,unsigned int dsttex,
                                                            int mode, int colormask
                                                            );


/*! @brief 通过四个源坐标点和四个目标坐标点计算出由源坐标变换到目标坐标的透视映射3x3变换矩阵(内存排序列优先,mat[col][row])
 *  @param[in] srcpoint  源坐标点(四个坐标点) 格式为float[4][2]( {x,y} = {srcpoint[index][0],srcpoint[index][1]})
 *  @param[in] dstpoint  目标坐标点(四个坐标点) 格式为float[4][2]( {x,y} = {dstpoint[index][0],dstpoint[index][1]})
 *  @param[out] resultMat 返回计算出的透视映射3x3变换矩阵，当计算未成功时返回单位矩阵(eye matrix)。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark  所有参数指针指向的内存由调用方申请和释放
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpWarpPerspective
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpGetPerspectiveTransform(float *srcpoint,float *dstpoint,
                                                                       float *resultMat);

/*! @brief 通过三个源坐标点和三个目标坐标点计算出由源坐标变换到目标坐标的几何映射2x3变换矩阵(内存排序列优先,mat[col][row])
 *  @param[in] srcpoint  源坐标点(三个坐标点) 格式为float[3][2]( {x,y} = {srcpoint[index][0],srcpoint[index][1]})
 *  @param[in] dstpoint  目标坐标点(三个坐标点) 格式为float[3][2]( {x,y} = {dstpoint[index][0],dstpoint[index][1]})
 *  @param[out] resultMat 返回计算出的透视映射2行3列变换矩阵，当计算未成功时返回单位矩阵({{1,0,0},{0,1,0})。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark  所有参数指针指向的内存由调用方申请和释放
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpGetAffineTransform(float *srcpoint,float *dstpoint,
                                                                  float *resultMat);


/*! @brief 通过3x3变换矩阵(内存排序列优先,mat[col][row])将纹理进行透视变换放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] mat3x3 3行3列透视变换矩阵 @ref glgpGetPerspectiveTransform
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext, 3x3变换矩阵内存排序列优先,mat[col][row]
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpGetPerspectiveTransform @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpWarpPerspective(unsigned int srctex,unsigned int dsttex,
                                                               float *mat3x3
                                                               );

/*! @brief 通过2x3变换矩阵(内存排序列优先,mat[col][row])将纹理进行几何变换放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @param[in] mat3x3 2行3列透视变换矩阵 @ref glgpgetAffineTransform
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext, 2x3变换矩阵内存排序列优先,mat[col][row]
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpgetAffineTransform @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpWarpAffine(unsigned int srctex,unsigned int dsttex,
                                                               float *mat2x3
                                                               );

/*! @brief 获取实现内部2维FFT变换的主要计算着色器代码,可用于根据硬件修改local_size_xy优化计算代码
 *  @param[in] void
 *  @return 返回代码的字符串指针
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpReplace2DFFTProgram
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL const char * glgpGet2DFFTShaderCode(void);


/*! @brief 替换内部2维FFT变换的主要计算着色器程序，可用于根据硬件修改local_size_xy优化计算代码
 *  @param[in] program opengl 程序对象号 @ref glgpComplieShaderProgram3,如果为0则切换为默认的程序
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa @ref glgpGetFenceSync @ref glgpDeleteSync
 *  @ref glgpGet2DFFTShaderCode @ref glgpCreateTex2DFFTPlan @ref glgpReleaseTex2DFFTPlan
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpReplace2DFFTProgram(unsigned int program);

typedef void * GLGP_FFTPlan2D;

/*! @brief 根据输入的纹理尺寸创建一个最多2维(可进行列方向、行方向、列行向变换)的FFT变换计划
 *  @param[in] tex  输入纹理，根据它的尺寸创建FFT变换计划
 *  @param[out] plan  返回变换计划到指向的内存中,反回的计划不再使用时应该进行释放 @ref glgpReleaseTexFFTPlan2D
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors 每维尺寸不能超过65536
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpReleaseTex2DFFTPlan @ref glgpExecTex2DFFTPlan
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext @ref glgpReleaseTexFFTPlan2D
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpCreateTex2DFFTPlan(unsigned int tex,GLGP_FFTPlan2D *plan);


/*! @brief 释放 @ref glgpCreateTexFFTPlan2D创建的FFT变换计划
 *  @param[in] plan  FFT变换计划
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors 每维尺寸不能超过65536
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpCreateTex2DFFTPlan @ref glgpExecTex2DFFTPlan
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpReleaseTex2DFFTPlan(GLGP_FFTPlan2D plan);


typedef enum{
    GLGP_TexFFTMode_ROW = 0,  //每行数据进行fft变换
    GLGP_TexFFTMode_COL,      //每列数据进行fft变换
    GLGP_TexFFTMode_ROW_COL,      //每行和每列数据进行fft变换
}TexFFTPlanExecMode;

typedef enum{
    GLGP_TexFFTDir_FFT = 0,  //进行fft变换
    GLGP_TexFFTDir_IFFT      //进行fft逆变换
}TexFFTPlanExecDir;

/*! @brief 执行 @ref glgpCreateTexFFTPlan2D创建的FFT变换计划
 *  @param[in] plan  FFT变换计划
 *  @param[in] srctex  进行FFT变换的源纹理； 1~4通道纹理，但只采用第一第二通道作实数和虚数
 *  @param[in] dsttex  FFT变换结果放置的目标纹理，必须为2通道单精度纹理
 *  @param[in] fftmode  FFT变换模式 @ref TexFFTPlanExecMode
 *  @param[in] fftdir  FFT变换方向 @ref TexFFTPlanExecDir
 *  @param[in] alpha  FFT变换前源纹理整体乘以的值; 如果是零相当于传入1; 如果是负数，变换前自动除以数据长度
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors 每维尺寸不能超过65536
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpCreateTex2DFFTPlan @ref glgpReleaseTex2DFFTPlan
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpExecTex2DFFTPlan(GLGP_FFTPlan2D plan,
                                                                unsigned int srctex, unsigned dsttex,
                                                                int fftmode,int fftdir,
                                                                float alpha
                                                                );


/*! @brief 获取 @ref glgpCreateTexFFTPlan2D创建的FFT变换计划优化过的输出纹理的尺寸，通过该尺寸可以读取到FFT之后的全部数据
 *  @param[in] plan  FFT变换计划
 *  @param[in] width  FFT变换计划化过的输出宽度，由调用都申请和释放内存，目前返回创建计划时纹理宽度的最接近2的整数幂 pow(2,n) >= width,min(n)
 *  @param[in] height  FFT变换计划划化过的输出高度，由调用都申请和释放内存，目前返回创建计划时纹理高度的最接近2的整数幂 pow(2,n) >= height,min(n)
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpCreateTex2DFFTPlan @ref glgpExecTex2DFFTPlan
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpGetTex2DFFTPlanOptimalSize(GLGP_FFTPlan2D plan,int *width, int *height);

typedef enum{
    GLGP_FFTWin_Hanning,    //汉宁窗 dst[n] = 0.5 * ( 1 - cos(2 * pi * n/(N-1) ) )
    GLGP_FFTWind_Hamming,   //海明窗 dst(n,a) = (1 - a ) - a cos(2*PI*n/(N-1))，a一般取0.46,也就是 dst[n] = (1 - 0.46 ) - 0.46 cos(2*PI*n/(N-1))
}FFTWindowType;

/*! @brief 根据目标buffer的长度，计算和填入指定长度的FFT 开窗数据
 *  @param[in] dstbuf  计算结果的放置目标缓冲指针，由调用方申请和释放内存; 注意缓冲区必须为复数(两通道)格式，如float[buflen][2]
 *  @param[in] complexlen  dstbuf缓冲区的长度,这个长度是指元素(双通道)长度
 *  @param[in] type  计算窗数据的类型，见 @ref FFTWindowType
 *  @return void
 *  @note
 *  @remark
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL void OPENGL_GP_LIBCALLMODE glgpGenFFTWindData(float *dstbuf, int complexlen, int type);


/*! @brief 把指定长度的FFT窗数据(双通道float[len][2])写入到2D FFT变换计划的指定方向的窗数据缓冲纹理
 *  @param[in] plan  FFT变换计划
 *  @param[in] rowORcol  写入到FFT变换计划行或列方向的窗数据缓冲纹理,只能是GLGP_TexFFTMode_ROW 或 GLGP_TexFFTMode_COL
 *  @param[in] srcbuf  窗数据源指针，由调用方申请和释放内存，当为NULL时设置FFT计划该方向不乘以窗数数据； 数据的格式为 float[buflen][2],列0为实况，列1为虚部
 *  @param[in] complexlen  dstbuf缓冲区的长度,这个长度是指元素(双通道)长度
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpCreateTex2DFFTPlan @ref glgpReleaseTex2DFFTPlan @ref glgpGenFFTWindData
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpSetTex2DFFTPlanWinData(GLGP_FFTPlan2D plan, int rowORcol,
                                                                      float *srcbuf, int complexlen
                                                                      );

/*! @brief 二维源纹理进行转置后放置到目标纹理
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,数据类型必须与源纹理相同
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTexTranspose(unsigned int srctex, unsigned int dsttex);


/*! @brief 二维源纹理进行一维直方图统计
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 应该为单通道32位无符号整数,宽高为 bins x 1
 *  @param[in] bins   直方图的条柱数量，应该大于0
 *  @param[in] rangestart  统计的像素值范围起始值，应该小于 rangeend
 *  @param[in] rangeend   统计的像素值范围结束值，应该大于 rangestart
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTex2DHist1DCalc(unsigned int srctex,unsigned int dsttex,
                                                               int bins,float rangestart,float rangeend);


/*! @brief 二维源纹理进行二维卷积运算
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道
 *  @param[in] kerneltex   二维卷积核，宽和高应该为大于2的单数, 必须是浮点数纹理
 *  @param[in] padding   卷积时超出源纹理边界进行填充的方式，0:填充0，1:填充边界值,2:填充边界镜像值
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTex2DConvolve2D(unsigned int srctex,unsigned int dsttex,
                                                               unsigned int kerneltex,
                                                               int padding,
                                                               int colormask
                                                               );

/*! @brief 二维源纹理填充入高斯滤波核数据
 *  @param[in] dsttex 目标纹理 仅支持1~4通道，应该为浮点数纹理,纹理的宽高应该为大于2的单数
 *  @param[in] sigma  高斯分布公式的标准差参数, 高斯分布公式为: {exp( -(x^2+y^2)/(2*PI*sigma^2))} / (2*PI*sigma^2)
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpFillTex2DGaussianKernel(unsigned int dsttex,float sigma);


/*! @brief 二维源纹理进行二维Sobel卷积运算,Sobel卷积核尺寸为3x3
 *  @param[in] srctex  源纹理 支持1~4通道
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道
 *  @param[in] direction  Sobel算子的方向，0表示X方向,1表示Y方向
 *  @param[in] padding   卷积时超出源纹理边界进行填充的方式，0:填充0，1:填充边界值,2:填充边界镜像值
 *  @param[in] colormask 对通道进行屏蔽，0b0001禁止alpha通道操作，0b1000禁止red通道操作。
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTex2DSobelConv(unsigned int srctex,unsigned int dsttex,int direction,
                                                              int padding,
                                                              int colormask
                                                              );

/*! @brief 二维源纹理进行Canny算法进行边缘检测,Canny算法内部求导Sobel卷积核尺寸为3x3
 *  @param[in] srctex  源纹理 支持1~4通道,但只会进行第一个通道的边缘检测
 *  @param[in] dsttex  目标纹理 仅支持单通道或四通道,但只会输出检测边缘结果到第一个通道
 *  @param[in] lowThresh  当Canny结果值小于lowThresh会被判定为噪声；而在 lowThresh~highThresh之间的值，如果其周围8点存在大于highThresh的像素，那么就会被保留为边缘
 *  @param[in] highThresh  当Canny结果值大于lowThresh会被判定为边缘；而在 lowThresh~highThresh之间的值，如果其周围8点存在大于highThresh的像素，那么就会被保留为边缘
 *  @param[in] padding   卷积时超出源纹理边界进行填充的方式，0:填充0，1:填充边界值,2:填充边界镜像值
 *  @return 成功返回零 失败返回非零
 *  @note
 *  @remark 需要锁定context才能调用 @ref glgpLockGLContext
 *  @errors
 *  @thread_safety 任何线程可执行.
 *  @sa
 *  @ref glgpLockGLContext  @ref glgpTrylockGLContext  @ref glgpUnlockGLContext
 *  @since
 *  @ingroup
 */
OPENGL_GP_LIBDLL int OPENGL_GP_LIBCALLMODE glgpTex2DCanny(unsigned int srctex,unsigned int dsttex,
                                                          float lowThresh,float highThresh,int padding);

#if defined(__cplusplus)||defined(c_plusplus)
}
#endif

#endif // OPENGL_GP_LIB_H
